  # #########################################
  # @Author: Quinn.chen
  # @Date: 2019-05-30 21:05:57
  # @Last Modified by:   Quinn.chen
  # @Last Modified time: 2019-05-30 21:05:57
  # ##########################################

import fnmatch
import os
import shutil

__all__ = ['file_or_fold_search_in_dir', 'get_total_size_of_fold', 'copy_file_or_fold_to_target', 'delete_file_or_fold']


def file_or_fold_search_in_dir(_dir, _file_key_word='*', _fold_key_word='*', _absolute_path=False ,_deep_search=0):
    """
    @ _dir: search in where dir
    @ _file_key_word: filter key word
    @ _absolute_path: return absolute path when True 
    @ _deep_search: deep search amount, find in first layer flod when 0
    """
    def absolute_filter_files(_root, _file, _keyword):
        if _keyword:
            if not fnmatch.fnmatch(_file, _keyword):
                return None
        if _absolute_path:
            _file = os.sep.join([os.path.abspath(_root), _file])
        return _file

    reslut = []
    source_deep = int(_deep_search) + 1
    _dir = os.path.expanduser(_dir)
    for root, dirs, files in os.walk(_dir):
        if root != './':
            current_deep = len((root.replace('./', '').split(os.sep)))
            if current_deep >= source_deep: # deep is max than search deep
                continue
        if _file_key_word:
            for _file in files:
                filter_file = absolute_filter_files(root, _file, _file_key_word)
                if filter_file:
                    reslut.append(filter_file)
        if _fold_key_word:
            for index, _fold in enumerate(dirs):
                filter_fold = absolute_filter_files(root, _fold, _fold_key_word)
                if not filter_fold:
                    dirs.pop(index)
    return reslut


def get_total_size_of_fold(_dir, **kwg):
    """
    @ _dir: where you want to search
    @ base on: file_or_fold_search_in_dir(xxx)
    """
    kwg.update({"_absolute_path": True})
    search_result = file_or_fold_search_in_dir(_dir, **kwg)
    total_size = 0
    try:
        for _file in search_result:
            total_size += os.path.getsize(_file)
        return total_size
    except KeyboardInterrupt: # not use ???
        print("total_size: {} in {}".format(total_size, _dir))


def copy_file_or_fold_to_target(_source_dir_or_file, _target_dir_or_file, _delete_source=False, **kwg):
    """
    @ _source_dir_or_file: source file or fold
    @ _target_dir_or_file: target file or fold
    @ _delete_source: weather should delete source
    @ base on: file_or_fold_search_in_dir, can search matched file to copy
    """
    _search_files = None
    copy_reslut = None
    if os.path.isfile(_source_dir_or_file):
        fpath, fname = os.path.split(_target_dir_or_file)
        if not os.path.exists(fpath):
            os.makedirs(fpath)
        copy_reslut = shutil.copy(_source_dir_or_file, _target_dir_or_file)
        print("Copy {} -> {}".format(_source_dir_or_file, _target_dir_or_file))
    elif os.path.isdir(_source_dir_or_file):
        if os.path.exists(_target_dir_or_file):
            _search_files = file_or_fold_search_in_dir(_dir=_source_dir_or_file, **kwg, _absolute_path=False, _deep_search=10000)
            for _file in _search_files:
                copy_reslut = copy_file_or_fold_to_target(_file, os.sep.join([_target_dir_or_file, _file.split(_source_dir_or_file)[-1]]), _delete_source)
        else:
            copy_reslut = shutil.copytree(_source_dir_or_file, _target_dir_or_file)
            print("Copy Tree {} -> {}".format(_source_dir_or_file, _target_dir_or_file))
    else:
        print("{} not exist!".format(_source_dir_or_file))
    
    if _delete_source and copy_reslut:
        delete_file_or_fold(_source_dir_or_file)
        if _search_files:
            delete_file_or_fold(_search_files)
    return copy_reslut


def delete_file_or_fold(_file_or_fold_path, **kwg):
    """
    @ _file_or_fold_path: delete fold or file
    @ base on: file_or_fold_search_in_dir
        can delete matched file
    """
    if kwg and os.path.isdir(_file_or_fold_path):
        _search_reslut = file_or_fold_search_in_dir(_file_or_fold_path, **kwg)
        for _file in _search_reslut:
            delete_file_or_fold(_file)
    else:
        if os.path.isfile(_file_or_fold_path):
            os.remove(_file_or_fold_path)
            print("Delete source {}".format(_file_or_fold_path))
        elif os.path.isdir(_file_or_fold_path):
            shutil.rmtree(_file_or_fold_path)
            print("Remove Tree {}".format(_file_or_fold_path))
        else:
            print("No Exist {}".format(_file_or_fold_path))


if __name__ == "__main__":
    # print(file_or_fold_search_in_dir('./123', '*', _absolute_path=False, _deep_search=2))
    # print(get_total_size_of_fold('./', _file_key_word='*.py', _fold_key_word="f*", _deep_search=1))
    # copy_file_or_fold_to_target('./123/quinn', '.\\quinn', _delete_source=True)
    search_file_later_than('./', None, None)
